"""
1一个完整的闭包函数必须满足哪几个条件
*2定义一个计算函数运行时间的装饰器（最少需要三种实现方式）作业未完成
3一个函数有多个装饰器，执行顺序是如何
"""
# 1:一个完整的闭包函数必须满足哪几个条件
"""
 答案A：
 1 必须有一个内嵌函数
 2:内层嵌套函数必须引用外部嵌套函数中的变量
 3：外部函数返回值必须是内嵌函数
 答案B：
1.函数A里面直接或者间接返回一个函数B。
2. 函数B里面使用着函数A里面的私有变量或者私有数据。
3. A函数在外面有一个变量来接收函数B，形成一个不会销毁的函数空间
疑问：函数A里面一定要私有变量吗？全局变量可以吗？
 """
# 2：定义一个计算函数运行时间的装饰器（最少需要三种实现方式）
# 函数式装饰器 （被装饰的是一个函数，返回函数值）
from functools import wraps
from time  import time
def calculator(func) :
    @wraps(func)
    # 定义嵌套函数，用来打印出装饰的函数的执行时间
    def wrapper(*args,**kwargs):
        # 定义开始时间和结束时间，将func夹在中间执行，取得其返回值
        start=time()
        func(*args,**kwargs)
        end=time()
        c=end-start
        # 打印方法名称和其执行时间
        print('该函数的运行时间为%f'% c)
    return wrapper
@calculator
def calculator_time(a,b):
    print(a^b)
calculator_time(5,6)

# 函数式装饰器 (传入参数为装饰的函数或方法)
def print_execute_time(func):
    from time import time
    # 定义嵌套函数，用来打印出装饰的函数的执行时间
    def wrapper(*args, **kwargs):
        # 定义开始时间和结束时间，将func夹在中间执行，取得其返回值
        start = time()
        func_return = func(*args, **kwargs)
        end = time()
        # 打印方法名称和其执行时间
        print(f'{func.__name__}() execute time: {end - start}s')
        # 返回func的返回值
        return func_return
    # 返回嵌套的内层函数
    return wrapper

# 函数式装饰器（被装饰的是一个类，返回函数值）


# 3一个函数有多个装饰器，执行顺序是如何:按照就近原则
#装饰器函数在被装饰函数定义好后立即执行从下往上执行
#函数调用时从上到下执行

def test1(func):
    def inner(*args, **kwargs):
        print("======test1 start001=====")  # 预计输出第一行
        func(*args, **kwargs)
        print("======test1 end003=====")  # 预计输出第三行
    return inner
def test2(func):
    def inner(*args, **kwargs):
        print("======test2 start002=====")  # 预计输出第二行
        func(*args, **kwargs)
        print("======test2 end004=====")  # 预计输出第4行
    return inner

@test1
@test2
def f():
    print("****self****")

f()

"""
输出：
======test1 start001=====
======test2 start002=====
****self****
======test2 end004=====
======test1 end003=====
"""
